package me.landery.modules.sinco.service.impl;

import cn.hutool.json.JSONObject;
import lombok.RequiredArgsConstructor;
import me.landery.exception.BadRequestException;
import me.landery.exception.EntityExistException;
import me.landery.modules.sinco.domain.*;
import me.landery.modules.sinco.domain.em.ProfitType;
import me.landery.modules.sinco.repository.ModeRepository;
import me.landery.modules.sinco.service.*;
import me.landery.modules.sinco.service.dto.ModeQueryCriteria;
import me.landery.modules.sinco.service.mapstruct.ModeMapper;
import me.landery.modules.sinco.service.mapstruct.VipMapper;
import me.landery.modules.sinco.util.CalculateUtil;
import me.landery.utils.PageUtil;
import me.landery.utils.QueryHelp;
import me.landery.utils.SecurityUtils;
import me.landery.utils.ValidationUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @Author cc.w
 * @Date 2022/6/7 17:38
 * @Version 1.0
 */
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "mode")
public class ModeServiceImpl implements ModeService {

    private final ModeRepository modeRepository;
    private final ModeMapper modeMapper;

    @Lazy
    @Autowired
    private VipService vipService;
    private final VipMapper vipMapper;

    private final OrderService orderService;

    @Autowired
    private ProfitService profitService;

    @Override
    public Map<String, Object> queryAll(ModeQueryCriteria criteria, Pageable pageable) {
        Page<Mode> page = modeRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(modeMapper::toDto).getContent(),page.getTotalElements());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Mode resources) {
        Mode mode = modeRepository.findByName(resources.getName());
        if(mode != null){
            throw new EntityExistException(Mode.class,"name",resources.getName());
        }
        modeRepository.save(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Set<Long> ids) {
        modeRepository.deleteAllByIdIn(ids);
        // 删除缓存
//        redisUtils.delByKeys(CacheKey.MO, ids);
    }

    @Override
    @CacheEvict(key = "'id:' + #p0.id")
    @Transactional(rollbackFor = Exception.class)
    public void update(Mode resources) {
        Mode mode = modeRepository.findById(resources.getId()).orElseGet(Mode::new);
        Mode old = modeRepository.findByName(resources.getName());
        if(old != null && !old.getId().equals(resources.getId())){
            throw new EntityExistException(Mode.class,"name",resources.getName());
        }
        ValidationUtil.isNull( mode.getId(),"Mode","id",resources.getId());
        resources.setId(mode.getId());
        modeRepository.save(resources);
    }

    /**
     * 用户订购套餐
     * @param modeId 套餐id
     */
    @Override
    @Transactional
    public JSONObject payMode(Long modeId) {
        if (modeId == 0){
            throw new BadRequestException("默认套餐，不需要重复购买");
        }
        //获取当前登陆用户的套餐信息
        Vip vip = vipMapper.toEntity(vipService.findByUserID(SecurityUtils.getCurrentUserId()));
        Mode modeDto = vip.getMode(); //当前套餐

        Optional<Mode> opMode = modeRepository.findById(modeId);
        JSONObject jsonObject = new JSONObject();
        Mode mode;
        if (opMode.isPresent()){
            mode = opMode.get();
        }else {
            throw  new BadRequestException("套餐不存在");
        }

        // 先算一下余额是否充足
        //1.1 算一下当前价格

        Date  now_date = new Date();
        Double needPrice = CalculateUtil.calculatePrice(mode);
        if (needPrice > vip.getBalance()){
            throw new BadRequestException("余额不足，请充值后重试");
        }

//        //按次付费不需要重复购买
//        if (modeDto.getId() == 0 && mode.getId() == 0){
//            throw  new BadRequestException("按次付费,不需要重复购买");
//        }


        vip.setBalance(vip.getBalance() - needPrice);
        vip.setMode(mode);
        vip.setQuota(vip.getQuota() + mode.getQuota()); //免费额度相加
        vip.setPrice(mode.getTax()); //续费价格替换
        // 处理有效时间，当前时间加上有效期
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now_date);
        calendar.add(Calendar.DATE,mode.getDay());
        vip.setExpiration(calendar.getTime());
        vipService.save(vip);

        //新建order订单
        Order order = new Order();
        order.setUser(vip.getUser());
        order.setMode(mode);
        order.setPrice(needPrice);
        order.setTime(now_date);
        order.setQuantity(1);

        //判断他的邀请码是否存在
        if (vip.getUser().getReferCode() != null){
            profitService.doProfit(vip.getUser(),vip.getUser().getReferCode(), ProfitType.PACKAGE,needPrice);
        }

        orderService.save(order);
        jsonObject.set("msg","购买成功");
        return jsonObject;
    }

    @Override
    public Mode findById(Long id) {
        return modeRepository.findById(id).orElse(null);
    }


}
